/**********************************************************************************************************************
** Name       : btsinfo.c
** Decription : main base and nearby base scan function
** Author     : jason_teng
** History    : 2022-12-30 Created
**********************************************************************************************************************/
#include "ql_api_nw.h"
#include "ql_api_sim.h"
#include "zq_gl.h"
#include "zq_app.h"
#include "btsinfo.h"

ql_task_t basescan_task;

static ql_mutex_t BaseScanMutex;
static char zq_BaseServer[ZQ_BASE_SCAN_BUFLEN] = {0};
static char zq_BaseNear[ZQ_BASE_SCAN_BUFLEN * ZQ_BASE_SCAN_NEAR_CNT];
static int zq_BaseNearCnt = -1;
//static uint8_t zq_SignalIntensity = 0; // 缺省值	

int GetSignalIntensity(void)
{
	//ql_rtos_mutex_lock(BaseScanMutex, 100);
	//// mqtt protocol p17, 信号强度，取值范围：0 到-113
	//ret = (zq_SignalIntensity < -113 || zq_SignalIntensity > 0)? -113 : zq_SignalIntensity;
	uint8_t csq = 99;
	ql_nw_get_csq(ZQ_SIM_0, &csq);
	if (csq < 3 || csq == 99)
		ZqSetErrCode(ZQ_ERR_CODE_SIGNAL, 1);
	else
		ZqSetErrCode(ZQ_ERR_CODE_SIGNAL, 0);
	if(zq_timer_s % 30 == 0)
		ZQLOG("Get signal intensity, csq: %d", csq);
	return csq;
}
void GetBtsInfo(char *buf, int sz)
{
	buf[0] = '\0';
	if (sz < ZQ_BASE_SCAN_BUFLEN) return;
	ql_rtos_mutex_lock(BaseScanMutex, 100);
	strncpy(buf, zq_BaseServer, sz);
	buf[sz-1] = 0;
	ql_rtos_mutex_unlock(BaseScanMutex);
	return;
}
//int GetNearBtsCnt(void)
//{
//	int ret;
//	ql_rtos_mutex_lock(BaseScanMutex, 10);
//	ret = (zq_BaseNearCnt <= 0) ? 0 : zq_BaseNearCnt;
//	ql_rtos_mutex_unlock(BaseScanMutex);
//	return ret;
//}
int GetNearBtsInfo(char *buf, int sz)
{
	int ret;
	buf[0] = '\0';
	if (sz < ZQ_BASE_SCAN_BUFLEN) return 0;
	ql_rtos_mutex_lock(BaseScanMutex, 100);
	strcpy(buf, zq_BaseNear);
	ret = (zq_BaseNearCnt <= 0) ? 0 : zq_BaseNearCnt;
	ql_rtos_mutex_unlock(BaseScanMutex);
	return ret;
}

//  -----------------------------------------------------------------------------------------------
static int zq_BaseInfoPkg(ql_nw_cell_info_s *pcell, char *pServer, char *pNear)
{
	ql_rtos_mutex_lock(BaseScanMutex, 100);
	zq_BaseNearCnt = 0;
	pServer[0] = '\0';
    if(pcell->gsm_info_valid)
    {
        for(int i = 0; i < pcell->gsm_info_num; i++)
        {
			ql_nw_gsm_cell_info_s *p = &(pcell->gsm_info[i]);
            if ((p->flag == 1) && (p->mcc != 0) &&(p->lac != 0) && (p->cid != 0))	//neigber cell
            {
				if (zq_BaseNearCnt >= ZQ_BASE_SCAN_NEAR_CNT) break;
				sprintf(pNear, "%d,%d,%u,%u,%d|", p->mcc, p->mnc, p->lac, p->cid, p->rssi);
				pNear += strlen(pNear);
				zq_BaseNearCnt++;
			}
            else if ((p->flag == 0) && (p->mcc != 0) && (p->lac != 0) && (p->cid != 0))	//serving cell
            {
				sprintf(pServer, "%d,%d,%u,%u,%d", p->mcc, p->mnc, p->lac, p->cid, p->rssi);
            }
        }
		// remove the last '|'
        if (zq_BaseNearCnt > 0) *(pNear-1) = '\0';
    }
    else if(pcell->lte_info_valid)
    {
        for(int i = 0; i < pcell->lte_info_num; i++)
        {
			ql_nw_lte_cell_info_s *p = &(pcell->lte_info[i]);
			if ((p->flag == 1) && (p->mcc != 0) &&(p->tac != 0) && (p->cid != 0))	//neigber cell
			{
				if (zq_BaseNearCnt >= ZQ_BASE_SCAN_NEAR_CNT) break;
				sprintf(pNear, "%d,%d,%u,%u,%d|", p->mcc, p->mnc, p->tac, p->cid, p->rssi);
				pNear += strlen(pNear);
				zq_BaseNearCnt++;
			}
            else if ((p->flag == 0) && (p->mcc != 0) && (p->tac != 0) && (p->cid != 0))	//serving cell
            {
				sprintf(pServer, "%d,%d,%u,%u,%d", p->mcc, p->mnc, p->tac, p->cid, p->rssi);
            }
        }
		// remove the last '|'
        if (zq_BaseNearCnt > 0) *(pNear-1) = '\0';
    }
	ql_rtos_mutex_unlock(BaseScanMutex);
	if(pServer[0] != '\0')
		return 0;
	else
    	return -1;
}

static void zq_BaseScanThread(void * arg)
{
	int err;
	ql_nw_cell_info_s cell_info = {0};

	for(int i = 0; i < 5; i++, ql_rtos_task_sleep_s(1)) { // 抛弃前五次，实测发现前2-3次扫描出来的周边基站偏少
		err = ql_nw_get_cell_info(ZQ_SIM_0, &cell_info);
		ZQLOG("Base station scan, discard first %d time", i+1);
	}
	// start a cell sync scan
    while(1)
    {
		// control next scan time
        if (zq_BaseNearCnt < 0)
			zq_BaseNearCnt = 0;
		else if(zq_BaseServer[0] == 0)
			ql_rtos_task_sleep_s(12);
        else
			ql_rtos_task_sleep_s(ZQ_BASE_SCAN_PERIOD);

		// get cell info
		ZqSetErrCode(ZQ_ERR_CODE_INVALID_SIM, 0);

		for(int i = 0; i < 40; i++, ql_rtos_task_sleep_s(1)) { // 不满足要求重试,
			err = ql_nw_get_cell_info(ZQ_SIM_0, &cell_info);
			ZQLOG("Base station scan, try ql_nw_get_cell_info %d time; return code: %d, nearby cell num: %d", i+1, err, cell_info.lte_info_num);
			if(QL_SIM_SUCCESS == err && cell_info.lte_info_valid && cell_info.lte_info_num > 1) // cell_info.lte_info_num > 1 -- 第1个时主基站，后面是周边基站，客人要求，尽量要有周边基站信息
				break;
		}
		// err = ql_nw_get_cell_info(ZQ_SIM_0, &cell_info);
		if(QL_SIM_SUCCESS == err) {
			err = zq_BaseInfoPkg(&cell_info, zq_BaseServer, zq_BaseNear);
			if (err != 0) 
				ZQLOG("@err@: Base Scna, zq_BaseInfoPkg");
			else
				ZQLOG("Base Scan, Server Cell: %s ---- Near Cell: %s", zq_BaseServer, zq_BaseNear);
		}
		else {
			ZQLOG("@err@: Base Scna, ql_nw_get_cell_info err: %d", err);
			if(err == QL_NW_SIM_ERR)
				ZqSetErrCode(ZQ_ERR_CODE_INVALID_SIM, 1);
		}
    }
}

void btsinfo_init(void)
{
	QlOSStatus err = ql_rtos_task_create(&basescan_task, 10 * 1024, APP_PRIORITY_NORMAL, "basescan", zq_BaseScanThread, NULL, 10);
	if(err != ZQ_RET_OK)
		ZQ_LOG_FAILED(btsinfo_init,  err);
	err = ql_rtos_mutex_create(&BaseScanMutex);
	if(err != ZQ_RET_OK)
		ZQ_LOG_FAILED(btsinfo_init, err);
}
